# -*- coding: utf-8 -*-

import unittest
import os.path
from os import system
import shutil
import mox


from kivy.app import App
from kivy.lang import Builder

from model.gamestate import Phase, GameState
from model import gamestate

from constants import PATH, CONFIG_FILE, CONFIG_TEMPLATE_FILE
from main import *
from ui.presenter_mock import PresenterMock


class TmpType(object):
    def bind(*kwargs):
        pass


class MainTest(unittest.TestCase):
    def setUp(self):
        self.mox = mox.Mox()

    def test_update_config(self):
        shutil.copyfile(CONFIG_TEMPLATE_FILE, 'data/config.ini.tmp')
        with open(CONFIG_FILE, 'w') as config:
            config.write('#2\n')
        with open(CONFIG_TEMPLATE_FILE, 'w') as template:
            template.write('#3\n')
        update_config()
        with open(CONFIG_FILE, 'r') as config:
            conf_ver = config.readline()
            self.assertEqual(conf_ver, '#3\n')

        with open(CONFIG_FILE, 'w') as config:
            config.write('#4\n')
        with open(CONFIG_TEMPLATE_FILE, 'w') as template:
            template.write('#3\n')
        update_config()
        with open(CONFIG_FILE, 'r') as config:
            conf_ver = config.readline()
            self.assertEqual(conf_ver, '#4\n')
        shutil.copyfile('data/config.ini.tmp', CONFIG_TEMPLATE_FILE)

    def test_build(self):
        self.mox.StubOutWithMock(Presenter, '__init__')
        Presenter.__init__(mox.IsA(MainView), PATH)
        self.mox.StubOutWithMock(MainViewApp, 'register_views')
        MainViewApp.register_views()
        self.mox.StubOutWithMock(MainViewApp, 'create_game_state_settings')
        MainViewApp.create_game_state_settings()
        self.mox.StubOutWithMock(MainViewApp,
                                 'update_confirmation_button_time')
        MainViewApp.update_confirmation_button_time()
        self.mox.StubOutWithMock(Presenter, 'change_phase')
        Presenter.change_phase(Phase.WELCOME)
        self.mox.StubOutWithMock(Presenter, 'resume_app')
        Presenter.resume_app()
        self.mox.StubOutWithMock(TmpType, 'bind')
        TmpType.bind(on_keyboard=mox.IgnoreArg())
        self.mox.ReplayAll()
        app = MainViewApp()
        app.build()
        app._app_window = TmpType()
        app.on_start()
        self.mox.VerifyAll()

    def test_register_view(self):
        app = MainViewApp()
        app.presenter = PresenterMock(Phase.WELCOME)
        app.register_views()

    def test_create_settings(self):
        app = MainViewApp()
        app.presenter = PresenterMock(Phase.WELCOME)
        app.presenter.game_state = GameState(None, None, None,
                                             None, None, None, None)
        app.create_game_state_settings()
        set_default = gamestate.Settings()
        self.assertEqual(app.presenter.game_state.settings,
                         gamestate.Settings())
        app.presenter.game_state = GameState(None, None, None,
                                             None, None, None,
                                             gamestate.Settings(1, 2, 3, 4, 5))
        app.create_game_state_settings()
        self.assertEqual(app.presenter.game_state.settings,
                         gamestate.Settings(1, 2, 3, 4, 5))

    @unittest.skip("Very strange test. Additionaly, it fails")
    def test_open_close_settings(self):
        app = MainViewApp()
        presenter = PresenterMock(Phase.WELCOME)
        app.presenter = presenter
        app.presenter.game_state = GameState(None, None, None,
                                             None, None, None, None)
        self.mox.StubOutWithMock(PresenterMock, 'set_orientation')
        PresenterMock.set_orientation(mox.IgnoreArg())
        self.mox.StubOutWithMock(App, 'open_settings')
        App.open_settings(['a', 'b'])
        self.mox.StubOutWithMock(PresenterMock, 'rotate')
        PresenterMock.rotate()
        self.mox.StubOutWithMock(PresenterMock, 'update')
        PresenterMock.update()
        self.mox.StubOutWithMock(App, 'close_settings')
        App.close_settings(['a', 'b'])
        self.mox.ReplayAll()
        app.open_settings(['a', 'b'])
        app.close_settings(['a', 'b'])
        self.mox.VerifyAll()

    def test_update_confirmation_button_time(self):
        app = MainViewApp()
        app.presenter = PresenterMock(Phase.WELCOME)
        app.presenter.settings.game.confirmation_time_sec = 0.5
        app.update_confirmation_button_time()
        from ui.confirmation_button import ConfirmationButton
        self.assertEqual(ConfirmationButton.time, 0.5)

    def test_on_close(self):
        app = MainViewApp()
        app.presenter = PresenterMock(Phase.WELCOME)
        self.mox.StubOutWithMock(PresenterMock, 'close_app')
        PresenterMock.close_app()
        PresenterMock.close_app()
        self.mox.ReplayAll()
        app.on_stop()
        app.on_pause()
        self.mox.VerifyAll()

    def test_main_ok(self):
        self.mox.StubOutWithMock(MainViewApp, 'run')
        MainViewApp.run()
        self.mox.ReplayAll()
        run_app()
        self.mox.VerifyAll()

    def test_main_fail(self):
        self.mox.StubOutWithMock(MainViewApp, 'run')
        MainViewApp.run().AndRaise(Exception)
        self.mox.StubOutWithMock(MainViewApp, 'on_stop')
        MainViewApp.on_stop()
        self.mox.ReplayAll()
        with open('data/pickled_gamestate.pkl', 'w') as f:
            f.write('5')
        with self.assertRaises(Exception):
            run_app()
        self.assertFalse(os.path.exists('data/pickled_gamestate.pkl'))
        self.mox.VerifyAll()

    def tearDown(self):
        self.mox.UnsetStubs()


if __name__ == '__main__':
    Builder.load_file(os.path.join(os.path.dirname(__file__),
                                   'mainview.kv'))
    unittest.main()
